﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Text;

namespace Devsoft.DB.Models.Crypto
{
    public class SimpleService : ICryptoService
    {

        public SimpleService(string key)
        {
            var md5 = MD5.Create();
            var  arr = md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(key));
            _secretBytes = arr;
        }
        public virtual string Encrypt(object val)
        {
            if (val == null)
            {
                return null;
            }

            using (var srcStream = new MemoryStream())
            {
                var formatter = new BinaryFormatter();
                formatter.Serialize(srcStream, val);
                srcStream.Seek(0, SeekOrigin.Begin);
                var cryptoProvider = new AesCryptoServiceProvider();
                using (var memoryStream = new MemoryStream())
                {
                    CryptoStream cryptoStream = new CryptoStream(memoryStream,
                    cryptoProvider.CreateEncryptor(_secretBytes, _secretBytes), CryptoStreamMode.Write);
                    var buf = srcStream.ToArray();
                    cryptoStream.Write(buf,0,buf.Length);
                    cryptoStream.FlushFinalBlock();
                    srcStream.Flush();
                    return Convert.ToBase64String(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
                }
            }
        }

        public virtual object Decrypt(string src)
        {
            if (String.IsNullOrEmpty(src))
            {
                return string.Empty;
                throw new ArgumentNullException("The string which needs to be decrypted can not be null.");
            }

            var cryptoProvider = new AesCryptoServiceProvider();
            MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(src));
            CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoProvider.CreateDecryptor(_secretBytes, _secretBytes), CryptoStreamMode.Read);
            var formatter = new BinaryFormatter();
            return formatter.Deserialize(cryptoStream);
        }

        public object Decrypt<T>(string src)
        {
            return (T) Decrypt(src);
        }
        private byte[] _secretBytes;
    }
}
